#include <windows.h>

#include "lib.h"
#include "rw1.h"

#define SELF	ReadersWritersProb1
#define SUPER	ReadersWriters

ReadersWritersProb1::ReadersWritersProb1()
  :  ReadersWriters()
{
	mutex = (PCRITICAL_SECTION)0;
	writer = (HANDLE)0;
	nReaders = 0;

	mutex = new CRITICAL_SECTION;
	if (!mutex)
		return;
	ZeroMemory(mutex, sizeof(CRITICAL_SECTION));
	InitializeCriticalSection(mutex);

	writer = CreateSemaphore(NULL, 1, 1, NULL);
}

ReadersWritersProb1::~ReadersWritersProb1()
{
	if (mutex)
	{
		DeleteCriticalSection(mutex);
		delete mutex;
		mutex = (PCRITICAL_SECTION)0;
	}

	if (writer)
	{
		CloseHandle(writer);
		writer = (HANDLE)0;
	}
}

bool8
ReadersWritersProb1::initOk()
{
	return (bool8)(mutex && writer);
}

bool8
ReadersWritersProb1::beginRead()
{
	EnterCriticalSection(mutex);
	if (++nReaders == 1)
	{
		if (WAIT_OBJECT_0 != WaitForSingleObject(writer, INFINITE))
		{
			--nReaders;
			LeaveCriticalSection(mutex);
			return false;
		}
	}
	LeaveCriticalSection(mutex);
	return true;
}

void
ReadersWritersProb1::endRead()
{
	EnterCriticalSection(mutex);
	if (--nReaders == 0)
		ReleaseSemaphore(writer, 1, NULL);
	LeaveCriticalSection(mutex);
}

bool8
ReadersWritersProb1::beginWrite()
{
	if (WAIT_OBJECT_0 != WaitForSingleObject(writer, INFINITE))
		return false;

    m_changeCount++;

	return true;
}

void
ReadersWritersProb1::endWrite()
{
	ReleaseSemaphore(writer, 1, NULL);
}
